package com.puzzle

import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Rect

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.core.graphics.createBitmap

// 图片控件
class PictureCtrl {
    private val mCallback: (PictureCtrl) -> Unit            // 回调
    private lateinit var mHasBorder: MutableState<Boolean>  // 有边框则为 true，否则为 false
    private val mImage: Bitmap                              // 图片
    private val mOriginalPosition: IntOffset                // 原位置，即刚被创建时的初始位置
    private lateinit var mPosition: MutableState<IntOffset> // 当前位置
    private val mSize: Int                                  // 尺寸

    /**
     * 构造方法。
     * @param callback  回调
     * @param image     图片
     * @param x, y      左上角坐标
     * @param size      尺寸
     */
    constructor(callback: (PictureCtrl) -> Unit, image: Bitmap, x: Int, y: Int, size: Int) {
        mCallback = callback
        mImage = createBitmap(size, size)
        mOriginalPosition = IntOffset(x, y)
        mSize = size
        Canvas(mImage).drawBitmap(image, Rect(x, y, (x + size), (y + size)), Rect(0, 0, size, size), null)
    }

    /**
     * 获取/设置边框标志。
     */
    var border: Boolean
        get() = mHasBorder.value
        set(value) {
            if (mHasBorder.value == value) {
                return
            }
            mHasBorder.value = value
        }

    /**
     * 画边框。
     * @param drawer    绘图者
     */
    private fun drawEdge(drawer: DrawScope) {
        drawer.drawLine(Const.COLOR_LEFT_TOP_1, Offset.Zero, Offset(mSize - 1f, 0f))
        drawer.drawLine(Const.COLOR_LEFT_TOP_1, Offset.Zero, Offset(0f, mSize - 1f))

        drawer.drawLine(Const.COLOR_LEFT_TOP_2, Offset(1f, 1f), Offset(mSize - 2f, 1f))
        drawer.drawLine(Const.COLOR_LEFT_TOP_2, Offset(1f, 1f), Offset(1f, mSize - 2f))

        drawer.drawLine(Const.COLOR_RIGHT_BOTTOM_1, Offset(mSize - 1f, 0f), Offset(mSize - 1f, mSize - 1f))
        drawer.drawLine(Const.COLOR_RIGHT_BOTTOM_1, Offset(0f, mSize - 1f), Offset(mSize - 1f, mSize - 1f))

        drawer.drawLine(Const.COLOR_RIGHT_BOTTOM_2, Offset(mSize - 2f, 1f), Offset(mSize - 2f, mSize - 2f))
        drawer.drawLine(Const.COLOR_RIGHT_BOTTOM_2, Offset(1f, mSize - 2f), Offset(mSize - 2f, mSize - 2f))
    }

    /**
     * 界面布局。
     */
    @Composable
    fun Greeting() {
        // 显示图片
        val size = mSize.toFloat() / LocalDensity.current.density
        Canvas(Modifier
            .size(size.dp)
            .offset {
                mPosition.value
            }
            .clickable {
                mCallback(this)
            }
        ) {
            // 画图片
            this.drawImage(mImage.asImageBitmap())

            // 画边框
            if (mHasBorder.value) {
                this@PictureCtrl.drawEdge(this)
            }
        }
    }

    /**
     * 初始化。
     */
    @Composable
    fun Init(hasBorder: Boolean) {
        mHasBorder = remember {
            mutableStateOf(hasBorder)
        }
        mPosition = remember {
            mutableStateOf(mOriginalPosition)
        }
    }

    /**
     * 判断自身是否在初始位置。
     * @return 在初始位置则返回 true，否则返回 false
     */
    fun isOnOriginalPosition(): Boolean {
        return mOriginalPosition == mPosition.value
    }

    /**
     * 获取/设置位置。
     */
    var position: IntOffset
        get() = mPosition.value
        set(value) {
            mPosition.value = value
        }

    /**
     * 获取尺寸。
     */
    val size: Int
        get() = mSize
}
